#include #include #include #include #include "installconf.h" #include "installconf.m" #include #include static const char K_INSTALLCONF[]="installconf"; static HELP_FILE help_selcateg (K_INSTALLCONF,"selcateg"); static HELP_FILE help_pkgcateg (K_INSTALLCONF,"pkgcateg"); #if defined(i386) #define ourarch "i386" #elif defined(powerpc) #define ourarch "powerpc" #elif defined(sparc) #define ourarch "sparc" #else #error Unsupported architecture #endif PUBLIC CATEG::CATEG(bool _suggested, const char *_name, bool _hidden) { name.setfrom (_name); suggested = _suggested; selected = suggested ? 1 : 0; hidden = _hidden; installed = false; nbinstalled = 0; } PUBLIC CATEGS::CATEGS( const char *path, // Path of the comps file const char *root) // Root (or NULL) of the installation { CATEGS *categs; CATEG *categ; char depcateg[200]; glocal.categs = this; glocal.categ = NULL; glocal.depcateg[0] = '\0'; api = package_api_init(K_INSTALLCONF); if (api != NULL){ api->setroot (api,root); }else{ xconf_error (MSG_U(E_NOPKGMANAGER,"No package manager available (module managerpm ?)!!!")); } (path,true); int ret = 0; int linelen = strlen(line); if (isdigit(line[0])){ const char *pt = str_skip(line); bool suggested = atoi(pt) != 0; pt = str_skip(pt+1); bool hide = false; if (strncmp(pt,"--hide ",7)==0){ hide = true; pt = str_skip(pt+7); } char title[linelen]; char *dst = title; while (*pt != '{' && *pt != '\0') *dst++ = *pt++; *dst = '\0'; strip_end (title); if (*pt == '{'){ glocal.categ = new CATEG(suggested,title,hide); glocal.categs->add (glocal.categ); } }else if (line[0] == '}'){ glocal.categ = NULL; }else if (isspace(line[0])){ const char *pt = str_skip (line); if (*pt == '@'){ // suggested category if this one is selected pt = str_skip(pt+1); glocal.categ->needs.add (new SSTRING(pt)); }else if (*pt == '?'){ // The following package are selected only // if this category is selected. pt = str_skip(pt+1); char *dst = glocal.depcateg; while (*pt != '{' && *pt != '\0') *dst++ = *pt++; *dst = '\0'; strip_end (glocal.depcateg); }else if (*pt == '}'){ glocal.depcateg[0] = '\0'; }else{ const char *dot = strchr(pt,':'); const char *name = pt; if (dot != NULL){ name = str_skip(dot+1); bool nnot = false; char arch[linelen]; char *dst = arch; if (*pt == '!'){ nnot = true; pt++; } while (pt < dot && *pt > ' ') *dst++ = *pt++; *dst = '\0'; if (strcmp(arch,ourarch)==0){ if (nnot) name = NULL; }else{ if (!nnot) name = NULL; } } if (name != NULL){ glocal.categ->pkgs.add (name,glocal.depcateg); } } }else if (line[0] != '\0'){ ret = -1; } return ret; } PUBLIC CATEGS::~CATEGS() { package_api_end (api); } PUBLIC CATEG *CATEGS::getitem (int no) const { return (CATEG*)ARRAY::getitem(no); } /* Select the suggested categories */ PUBLIC void CATEGS::selectsug() { for (int i=0; iselected = c->suggested ? 1 : 0; } } PUBLIC void CATEGS::selectall() { for (int i=0; iselected = 1; } } PUBLIC void CATEGS::unselectall() { for (int i=0; iselected = 0; } } /* Find out which categories are currently installed Return -1 if any errors */ PUBLIC int CATEGS::setmissing( const char *root) { int ret = -1; SSTRINGS lst; if (api->listinstalled(api,lst)!=-1){ ret = 0; // We have to walk each category to find out if // at least one package is not installed for (int i=0; iinstalled = true; SSTRING_KEYS *cpkgs = &c->pkgs; for (int j=0; jgetnb(); j++){ const char *pkg = cpkgs->getitem(j)->get(); int lk = lst.lookup(pkg); if (lk != -1) c->nbinstalled++; if (lk==-1){ // This package is not installed, or not fully // fprintf (stderr,"setmissing categ :%s: pkg missing :%s:\n",c->name.get(),pkg); c->installed = false; } } } } return ret; } /* Select the package categories to install or uninstall */ PUBLIC int CATEGS::select(SHOW_MODE mode) { int ret = -1; DIALOG dia; for (int i=0; ihidden) continue; bool some_installed = c->nbinstalled > 0; if (mode == SHOW_ALL || (mode == SHOW_UNINSTALLED && ! c->installed) || (mode == SHOW_INSTALLED && some_installed)){ if (some_installed && !c->installed){ char buf[100]; snprintf (buf,sizeof(buf)-1,"%s (%s: %d/%d)",c->name.get() ,MSG_U(I_PARTIALLY,"Partially installed") ,c->nbinstalled,c->pkgs.getnb()); dia.newf_chk ("",c->selected,buf); }else{ dia.newf_chk ("",c->selected,c->name.get()); } } } int nof = 0; dia.setbutinfo (MENU_USR1,MSG_U(B_ALL,"All"),MSG_R(B_ALL)); dia.setbutinfo (MENU_USR2,MSG_U(B_NONE,"None"),MSG_R(B_NONE)); int menubut = MENUBUT_USR1|MENUBUT_USR2; if (mode == SHOW_UNINSTALLED){ dia.setbutinfo (MENU_USR3,MSG_U(B_RESET,"reset"),MSG_R(B_RESET)); menubut |= MENUBUT_USR3; } while (1){ MENU_STATUS code = dia.edit (MSG_U(T_SELCATEG ,"Select package categories") ,MSG_U(I_SELCATEG,"") ,help_selcateg ,nof,MENUBUT_CANCEL|MENUBUT_ACCEPT|menubut); if (code == MENU_CANCEL || code == MENU_ESCAPE){ break; }else if (code == MENU_USR1){ selectall(); dia.reload(); }else if (code == MENU_USR2){ unselectall(); dia.reload(); }else if (code == MENU_USR3){ selectsug(); dia.reload(); }else{ ret = 0; break; } } return ret; } PUBLIC CATEG* CATEGS::lookup (const char *name) { CATEG *ret = NULL; for (int i=0; iname.cmp(name)==0){ ret = c; break; } } return ret; } /* Extract the list of packages in the selected categories */ PUBLIC int CATEGS::pickselected (SSTRINGS &lst) { for (int i=0; iselected){ SSTRING_KEYS *cpkgs = &c->pkgs; for (int j=0; jgetnb(); j++){ SSTRING_KEY *k = cpkgs->getitem(j); const char *dep = k->getobjval(); const char *pkg = k->get(); // fprintf (stderr,"pickselected categ=:%s: pkg=:%s: dep=:%s:\n",c->name.get() // ,pkg,dep); if (dep[0] == '\0'){ lst.add (new SSTRING(pkg)); }else{ // This package is selected only if // the category dep is selected CATEG *depcat = lookup(dep); if (depcat != NULL && depcat->selected){ // fprintf (stderr,"depcat selected\n"); lst.add (new SSTRING(pkg)); }else{ //fprintf (stderr,"depcat NOT selected\n"); } } } } } return 0; } /* Select the categories required by the already selected categories. */ PUBLIC int CATEGS::selectsuggested () { for (int i=0; iselected){ for (int j=0; jneeds.getnb(); j++){ CATEG *cc = lookup(c->needs.getitem(j)->get()); if (cc != NULL) cc->selected = 1; } } } return 0; } /* Install the packages from the selected categories */ PUBLIC int CATEGS::install(const char *root, const char *srcdir) { int ret = -1; selectsuggested(); SSTRINGS lst; pickselected (lst); ret = api->installpkgs (api,lst,srcdir,"CD title"); return ret; } /* Check if the comps files was loaded properly and the manage rpm module is available */ PUBLIC bool CATEGS::isok() { return getnb() > 0 && api != NULL; } void comps_menu (const char *cdpath, const char *root) { static const char *install = MSG_U(M_INSTCATEG,"package categories"); static const char *remove = MSG_U(M_REMCATEG,"package categories"); static const char *tbopt[]={ MSG_U(M_INSTALL,"Install"), install, MSG_U(M_REMOVE,"Remove"), remove, NULL }; DIALOG_MENU dia; dia.new_menuitems (tbopt); int nof = 0; while (1){ MENU_STATUS code = dia.editmenu (MSG_U(T_PKGCATEG ,"Manage software categories") ,"" ,help_pkgcateg ,nof,0); if (code == MENU_ESCAPE || code == MENU_QUIT){ break; }else if (perm_rootaccess(MSG_R(P_INSTALLCONF))){ const char *sel = dia.getmenustr(nof); char pathcomp[PATH_MAX]; snprintf (pathcomp,sizeof(pathcomp)-1,"%s/base/comps",cdpath); char pathrpms[PATH_MAX]; snprintf (pathrpms,sizeof(pathrpms)-1,"%s/RPMS",cdpath); CATEGS comps (pathcomp,root); if (comps.isok()){ if (sel == install){ comps.selectsug(); if (comps.setmissing (root) != -1 && comps.select (SHOW_UNINSTALLED) != -1){ comps.install(root,pathrpms); } }else if (sel == remove){ comps.unselectall(); if (comps.setmissing (root) != -1 && comps.select (SHOW_INSTALLED) != -1){ // comps.uninstall(root); } } } } } }