diff --git a/ports-mgmt/pkg_cleanup/Makefile b/ports-mgmt/pkg_cleanup/Makefile index 69e705f4c8d5..9a5f4dfc203b 100644 --- a/ports-mgmt/pkg_cleanup/Makefile +++ b/ports-mgmt/pkg_cleanup/Makefile @@ -2,20 +2,18 @@ # $FreeBSD$ PORTNAME= pkg_cleanup -PORTVERSION= 1.1 +PORTVERSION= 2.0 CATEGORIES= ports-mgmt DISTFILES= MAINTAINER= shurd@sasktel.net COMMENT= Interactive program for deinstalling 'leaf' packages -MAN1= pkg_cleanup.1 - WRKSRC= ${WRKDIR}/${PORTNAME} -PLIST_FILES= sbin/pkg_cleanup +PLIST_FILES= sbin/pkg_cleanup \ + man/man1/pkg_cleanup.1.gz -NO_STAGE= yes .include .if ${OSVERSION} >= 900000 && ${OSVERSION} < 900038 @@ -33,7 +31,7 @@ do-build: make -C ${WRKSRC} do-install: - ${INSTALL_PROGRAM} ${WRKSRC}/pkg_cleanup ${PREFIX}/sbin/pkg_cleanup - ${INSTALL_MAN} ${WRKSRC}/pkg_cleanup.1 ${MAN1PREFIX}/man/man1 + ${INSTALL_PROGRAM} ${WRKSRC}/pkg_cleanup ${STAGEDIR}${PREFIX}/sbin/pkg_cleanup + ${INSTALL_MAN} ${WRKSRC}/pkg_cleanup.1 ${STAGEDIR}${MAN1PREFIX}/man/man1 .include diff --git a/ports-mgmt/pkg_cleanup/files/pkg_cleanup.c b/ports-mgmt/pkg_cleanup/files/pkg_cleanup.c index 000045327b55..9e282719c42f 100644 --- a/ports-mgmt/pkg_cleanup/files/pkg_cleanup.c +++ b/ports-mgmt/pkg_cleanup/files/pkg_cleanup.c @@ -9,9 +9,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -20,6 +22,14 @@ #endif static glob_t gl; /* A cached list of all files in /var/db/pkg */ +static StringList *sl; +static size_t pathc; +static char **pathv; +static bool uses_pkg; +static int menulen=0; +static int helpfile=-1; +static char *helpfname="/tmp/pkgcleanup.XXXX"; + #ifdef OLD_DIALOG typedef dialogMenuItem ListItem; #else @@ -36,7 +46,17 @@ ListItem *menu; #define ITEM_CHECKED state #endif -int menulen=0; +bool check_pkg(void) +{ + if(WEXITSTATUS(system("TMPDIR=/dev/null " + "ASSUME_ALWAYS_YES=1 " + "PACKAGESITE=file:///nonexistent " + "pkg info -x 'pkg(-devel)?$' " + ">/dev/null 2>&1") + )==0) + return true; + return false; +} void free_menu(void) { @@ -68,6 +88,66 @@ int blacklist(char *path, int operation) return(hsearch(item, operation)!=NULL); } +char *read_desc(char *path) +{ + if(uses_pkg) { + char newpath[MAXPATHLEN+1]; + char *p=NULL; + char *np=NULL; + FILE *pkg; + char chunk[1024]; + size_t cs, len=0; + + sprintf(newpath,"/usr/sbin/pkg query %%e \"%s\"", path); + fflush(stdout); + pkg=popen(newpath, "r"); + if(!pkg) + return NULL; + while((cs=fread(chunk, 1, sizeof(chunk), pkg))) { + np=(char *)realloc(p, len+cs+1); + if(!np) { + pclose(pkg); + free(p); + return NULL; + } + p=np; + memcpy(p+len, chunk, cs); + len+=cs; + p[len]=0; + } + pclose(pkg); + if(len==0) { + free(p); + return NULL; + } + return p; + } + else { + char *p; + char newpath[MAXPATHLEN+1]; + FILE *file; + struct stat sb; + + sprintf(newpath,"/var/db/pkg/%s/+DESC",path); + file=fopen(newpath, "r"); + if(file) { + if(fstat(fileno(file), &sb)==0) { + p=(char *)malloc(sb.st_size+1); + if(p) { + if(fread(p, sb.st_size, 1, file)==1) { + fclose(file); + p[sb.st_size]=0; + return p; + } + free(p); + } + } + fclose(file); + } + } + return NULL; +} + #ifdef OLD_DIALOG int fire(struct _dmenu_item *item) { @@ -89,8 +169,19 @@ void selected(struct _dmenu_item *item, int is_selected) wattrset(stdscr, dialog_attr); mvwaddnstr(stdscr, 4, 4, (char *)item->data, maxx-6); wrefresh(stdscr); - sprintf(path,"/var/db/pkg/%s/+DESC",item->prompt); - use_helpfile(path); + if(uses_pkg) { + char *desc=read_desc(item->prompt); + lseek(helpfile, 0, SEEK_SET); + if(desc) { + write(helpfile, desc, strlen(desc)); + free(desc); + } + ftruncate(helpfile, lseek(helpfile, 0, SEEK_CUR)); + } + else { + sprintf(path,"/var/db/pkg/%s/+DESC",item->prompt); + use_helpfile(path); + } } } @@ -102,19 +193,74 @@ int checked(struct _dmenu_item *item) } #endif +char *read_comment(char *path) +{ + if(uses_pkg) { + char newpath[MAXPATHLEN+1]; + char *p=NULL; + char *np=NULL; + FILE *pkg; + char chunk[1024]; + size_t cs, len=0; + + sprintf(newpath,"/usr/sbin/pkg query %%c \"%s\"", path); + fflush(stdout); + pkg=popen(newpath, "r"); + if(!pkg) + return strdup(""); + while((cs=fread(chunk, 1, sizeof(chunk), pkg))) { + np=(char *)realloc(p, len+cs+1); + if(!np) { + pclose(pkg); + free(p); + return strdup(""); + } + p=np; + memcpy(p+len, chunk, cs); + len+=cs; + p[len]=0; + } + pclose(pkg); + if(len==0) { + free(p); + return strdup(""); + } + return p; + } + else { + char comment[80]; + FILE *file; + char newpath[MAXPATHLEN+1]; + char *p; + + /* Read +COMMENT */ + sprintf(newpath,"%s/+COMMENT",path); + file=fopen(newpath,"r"); + if(file) { + fgets(comment, sizeof(comment), file); + fclose(file); + /* Remove trailing whitespace */ + for(p=strchr(comment,0)-1; p>=comment; p--) { + if(isspace(*p)) + *p=0; + else + break; + } + return strdup(comment); + } + } + return strdup(""); +} + /* Read +COMMENT, add to menu and blacklist */ -int add_item(char *path) +int add_item(char *path, char *comment) { char *p; - char comment[80]; - FILE *file; - char newpath[MAXPATHLEN+1]; ListItem *newmenu; if(blacklist(path,FIND)) return(0); blacklist(path,ENTER); - comment[0]=0; newmenu=(ListItem *)realloc(menu, sizeof(ListItem)*(menulen+1)); if(newmenu==NULL) @@ -122,10 +268,12 @@ int add_item(char *path) menu=newmenu; p=strrchr(path,'/'); - if(p==NULL) /* Not possible */ - return(-1); + if(p==NULL) + p=path; + else + p++; - menu[menulen].ITEM_PROMPT=strdup(p+1); + menu[menulen].ITEM_PROMPT=strdup(p); menu[menulen].ITEM_CHECKED=0; #ifdef OLD_DIALOG menu[menulen].title=""; @@ -139,20 +287,6 @@ int add_item(char *path) menu[menulen].text=""; #endif - /* Read +COMMENT */ - sprintf(newpath,"%s/+COMMENT",path); - file=fopen(newpath,"r"); - if(file) { - fgets(comment, sizeof(comment), file); - fclose(file); - /* Remove trailing whitespace */ - for(p=strchr(comment,0)-1; p>=comment; p--) { - if(isspace(*p)) - *p=0; - else - break; - } - } menu[menulen].ITEM_DATA=strdup(comment); menulen++; @@ -187,28 +321,12 @@ int display_menu(void) loop: switch(ret=dlg_checklist("Welcome to pkg_cleanup.", "These are the leaf packages installed on your system\nChose the packages to deinstall. Help will display the package description.", maxy-1, maxx, maxy-9, menulen, menu, " X", FLAG_CHECK, &curr)) { case DLG_EXIT_HELP: { - char *p; - char newpath[MAXPATHLEN+1]; - FILE *file; - struct stat sb; - - /* READ +DESC */ - sprintf(newpath,"/var/db/pkg/%s/+DESC",menu[curr].ITEM_PROMPT); - file=fopen(newpath, "r"); - if(file) { - if(fstat(fileno(file), &sb)==0) { - p=(char *)malloc(sb.st_size+1); - if(p) { - if(fread(p, sb.st_size, 1, file)==1) { - p[sb.st_size]=0; - dialog_vars.help_button=0; - dialog_msgbox(menu[curr].ITEM_DATA, p, maxy-4, maxx-4, TRUE); - dialog_vars.help_button=1; - } - free(p); - } - } - fclose(file); + char *p = read_desc(menu[curr].ITEM_PROMPT); + if(p) { + dialog_vars.help_button=0; + dialog_msgbox(menu[curr].ITEM_DATA, p, maxy-4, maxx-4, TRUE); + dialog_vars.help_button=1; + free(p); } goto loop; } @@ -226,90 +344,161 @@ loop: return(ret); } -/* Goes through the glob contents, looking for zero-length +REQUIRED-BY */ -int read_pkglist(int loops) +bool is_leaf_package(char *path) { - char path[MAXPATHLEN+1]; - int p; + char newpath[MAXPATHLEN+1]; struct stat sb; - int maxx,maxy; - int lastgauge=-1; - int gauge; -#ifndef OLD_DIALOG - int pipepair[2]; - FILE *read_pipe; - FILE *write_pipe; -#endif - do_init_dialog(); - getmaxyx(stdscr, maxy, maxx); - for(p=0;pline && isspace(*p); p--) + *p=0; + p=strtok(line, "\t"); + p=strtok(NULL, "\0"); + add_item(line, p?p:""); + } + if(WEXITSTATUS(pclose(pkg)) && menulen==0) { + fputs("pkg returned an error.\n", stderr); + return -1; + } #ifdef OLD_DIALOG - dialog_gauge(NULL, "Searching for leaves", maxy/2-1, maxx/2-12, 7, 24, 100); - dialog_clear_norefresh(); + dialog_clear_norefresh(); #else - if(pipe(pipepair)!=0) { - fputs("Cannot create pipe pair.\n", stderr); - return(-1); - } - if((read_pipe=fdopen(pipepair[0], "r"))==NULL) { - fputs("Cannot open read end of pipe pair.\n", stderr); - return(-1); - } - dialog_state.pipe_input=read_pipe; - if((write_pipe=fdopen(pipepair[1], "r"))==NULL) { - fputs("Cannot open read end of pipe pair.\n", stderr); - return(-1); - } - fprintf(write_pipe, "%d\n%c", 100, 4); - fclose(write_pipe); - dialog_gauge(NULL, "Searching for leaves", maxy/2-1, maxx/2-12, 100); - fclose(read_pipe); - dlg_clear(); + dlg_clear(); #endif + } + else { + int p; + int maxx,maxy; + int lastgauge=-1; + int gauge; + char *comment; +#ifndef OLD_DIALOG + int pipepair[2]; + FILE *read_pipe; + FILE *write_pipe; +#endif + + do_init_dialog(); + getmaxyx(stdscr, maxy, maxx); + for(p=0;p 0 && line[len-1]=='\n') + len--; + nline = strndup(line, len); + if(!nline) { + fprintf(stderr, "Unable allocate memory for \"%.*s\" to list\n", (int)len, line); + return EX_UNAVAILABLE; + } + if(sl_add(sl, nline)) { + fprintf(stderr, "Unable to add package \"%s\" to list\n", nline); + return EX_UNAVAILABLE; + } + } + ret = pclose(pkg); + if(WEXITSTATUS(ret)) { + fprintf(stderr, "pkg exited with error %d\n", WEXITSTATUS(ret)); + return WEXITSTATUS(ret); + } + + pathc = sl->sl_cur; + pathv = sl->sl_str; + } + else { + /* glob() package directories */ + if(glob("/var/db/pkg/*", GLOB_ERR, NULL, &gl)) { + fputs("Unable to get list of packages\n",stderr); + switch(errno) { + case GLOB_NOSPACE: + return(EX_UNAVAILABLE); + case GLOB_ABORTED: + return(EX_NOINPUT); + case GLOB_NOMATCH: + return(EX_NOINPUT); + } + return(EXIT_FAILURE); + } + pathc = gl.gl_pathc; + pathv = gl.gl_pathv; + } + return 0; +} + /* * The hash table is to keep track of leaves which have already been displayed * to the user. */ int main(int argc, char **argv) { - char **pathv; - struct stat sb; - int loops=0; + int i; - /* glob() package directories */ - if(glob("/var/db/pkg/*", GLOB_ERR, NULL, &gl)) { - fputs("Unable to get list of packages\n",stderr); - switch(errno) { - case GLOB_NOSPACE: - return(EX_UNAVAILABLE); - case GLOB_ABORTED: - return(EX_NOINPUT); - case GLOB_NOMATCH: - return(EX_NOINPUT); - } - return(EXIT_FAILURE); - } + uses_pkg = check_pkg(); - if(gl.gl_pathc==0) { + i = glob_packages(); + if(i) + return i; + + if(pathc==0) { fputs("No packages found.\n",stderr); return(EXIT_FAILURE); } /* Initialize space for blacklist hash table */ - if(hcreate(1000)==0) { + if(hcreate(10000)==0) { fputs("Cannot create hash table.\n",stderr); return(EX_UNAVAILABLE); } + /* Create temp help file for the description when using pkg on 8.x */ +#ifdef OLD_DIALOG + if(uses_pkg) + helpfile=mkstemp(helpfname); +#endif + + i=0; do { - if(read_pkglist(loops++)) + if(read_pkglist(i++)) break; if(display_menu()) break; @@ -436,6 +696,13 @@ int main(int argc, char **argv) free_menu(); } while(keep_going()); +#ifdef OLD_DIALOG + if(helpfile != -1) { + close(helpfile); + unlink(helpfname); + } +#endif + fputs("\nProgram Terminated Successfully\n",stderr); return(0); }