/* * Copyright (c) 2005 * iMil . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by iMil. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY iMil AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL iMil OR THE VOICES IN HIS HEAD * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * * $Id: install_many.c,v 1.18 2005/08/17 08:16:19 imil Exp $ */ #include "pkg_select.h" struct pkg_list { char *pkg; SLIST_ENTRY(pkg_list) next; }; static char **build_list_from_slist(void); static void del_pkg(const char *); static SLIST_HEAD(, pkg_list) top = SLIST_HEAD_INITIALIZER(top); static int count = 0; static char ** build_list_from_slist() { int i; char *p, **list; struct pkg_list *plist; XMALLOC(list, (count + 1) * sizeof(char *)); list[count] = NULL; i = count; i--; SLIST_FOREACH(plist, &top, next) { if ((p = strrchr(plist->pkg, '/')) != NULL) p++; else p = plist->pkg; XSTRDUP(list[i], p); i--; } return(list); } void free_tbi_pkgs() { struct pkg_list *plist; while (!SLIST_EMPTY(&top)) { plist = SLIST_FIRST(&top); SLIST_REMOVE_HEAD(&top, next); XFREE(plist->pkg); XFREE(plist); } count = 0; } int tb_installed(const char *pkg) { char *p; struct pkg_list *plist; if (SLIST_EMPTY(&top)) return(T_FALSE); SLIST_FOREACH(plist, &top, next) { /* add_pkg check, based on full path */ if (strchr(pkg, '/') != NULL) { if (strcmp(pkg, plist->pkg) == 0) return(T_TRUE); else continue; } /* combo select check, based on pkg name */ if ((p = strrchr(plist->pkg, '/')) != NULL) { p++; if (strcmp(pkg, p) == 0) return(T_TRUE); } } return(T_FALSE); } void del_pkg(const char *pkg) { int len1, len2; struct pkg_list *plist; char *p; if (pkg == NULL) return; SLIST_FOREACH(plist, &top, next) { if (plist != NULL && plist->pkg != NULL) { /* full path size */ len1 = strlen(plist->pkg); /* pkg size */ len2 = strlen(pkg); if (len1 < len2) continue; /* point to pkg name if char *pkg is a full path */ p = &(plist->pkg)[len1 - len2]; if (strcmp(p, pkg) == 0) { SLIST_REMOVE(&top, plist, pkg_list, next); XFREE(plist->pkg); XFREE(plist); count--; return; } } } } void add_pkg(const char *pkg) { struct pkg_list *p; /* 1st, insert the >> Next item */ if (SLIST_EMPTY(&top)) { XMALLOC(p, sizeof(struct pkg_list)); XSTRDUP(p->pkg, NEXT); SLIST_INSERT_HEAD(&top, p, next); count++; } if (tb_installed(pkg)) { /* already marked, remove */ del_pkg(pkg); return; } XMALLOC(p, sizeof(struct pkg_list)); XSTRDUP(p->pkg, pkg); SLIST_INSERT_HEAD(&top, p, next); count++; } void process_many(int action) { char c, *p, *resp, **list, txt[MIDLEN], flags[5]; const char *msg; int h, w, y, x; Etree **etree; struct pkg_list *plist; c = 0; if (SLIST_EMPTY(&top)) return; h = LINES - 4; w = COLS / 1.5; y = 0; x = (COLS - w) / 2; snprintf(txt, MIDLEN, "[ %s ]", NEXT); print_kb(txt, "proceed", LINES - 2, x); print_kb(ps_back.icon, ps_back.descr, LINES - 2, x + strlen(txt) + 10); refresh(); resp = NULL; do { /* map SLIST to a simple char ** list */ if ((list = build_list_from_slist()) == NULL) goto out; if ((etree = build_tree_from_list(list)) == NULL) goto out; XFREE(resp); if (action == COMBO_INST) msg = PKG_TB_INST; else msg = PKG_TB_DEINST; resp = combo_select(etree, msg, h, w, y, x, 1); if (resp == NULL) return; /* they said "counter-intuitive" :) let it there, we may find a use.. if (strcmp(resp, NEXT) != 0) del_pkg(resp); */ } while (strcmp(resp, NEXT) != 0); XFREE(resp); clear(); refresh(); if (action == COMBO_INST) c = mid_getch_popup("install type", "(b)inaries / (s)ources ?"); if (action == COMBO_DEINST) { c = mid_getch_popup("confirmation", REALLY_MASS_DELETE); if (c == 'n') /* default is Y */ goto out; XSTRCPY(flags, "-v"); if (c == 'r') XSTRCAT(flags, "r"); } SLIST_FOREACH(plist, &top, next) { if ((p = strrchr(plist->pkg, '/')) == NULL) goto out; p++; /* p now points to pkg name */ if (action == COMBO_DEINST) pkg_tool("delete", p, flags, DONT_WAIT); else { /* install: bins or sources ? */ if (c == 'b') { set_pkg_path(conf.pkg_path); pkg_tool("add", p, "-v", DONT_WAIT); } if (c == 's') { pkgsrc_make("install", plist->pkg, DONT_WAIT); } } /* COMBO_INST */ } out: free_nodir_tree(&etree); free_list(&list); free_tbi_pkgs(); }