diff options
author | Raphael Kubo da Costa <rakuco@FreeBSD.org> | 2014-01-06 00:51:33 +0000 |
---|---|---|
committer | Raphael Kubo da Costa <rakuco@FreeBSD.org> | 2014-01-06 00:51:33 +0000 |
commit | 0222abaedeb0080498d59b960fbb764958f1f608 (patch) | |
tree | 7b1a6cfbe9382bcc814e11f83b0f7a9768e23c1b /ports-mgmt | |
parent | addd6f1083af45ef234412e0946ad97ea643e501 (diff) | |
download | ports-0222abaedeb0080498d59b960fbb764958f1f608.tar.gz ports-0222abaedeb0080498d59b960fbb764958f1f608.zip |
Notes
Diffstat (limited to 'ports-mgmt')
-rw-r--r-- | ports-mgmt/pkg_cleanup/Makefile | 12 | ||||
-rw-r--r-- | ports-mgmt/pkg_cleanup/files/pkg_cleanup.c | 533 |
2 files changed, 405 insertions, 140 deletions
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 <bsd.port.pre.mk> .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 <bsd.port.post.mk> 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 <errno.h> #include <glob.h> #include <search.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <stringlist.h> #include <sysexits.h> #include <unistd.h> @@ -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;p<gl.gl_pathc;p++) { - gauge=p*100/gl.gl_pathc; - if(gauge != lastgauge) { -#ifdef OLD_DIALOG - dialog_gauge(NULL, "Searching for leaves", maxy/2-1, maxx/2-12, 7, 24, gauge); -#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); + if(uses_pkg) { + FILE *pkg; + char val[32]; + long v; + + sprintf(newpath,"/usr/sbin/pkg query \"%%#r%%k\" \"%s\"", path); + fflush(stdout); + pkg=popen(newpath,"r"); + if(pkg) { + if(fgets(val, sizeof(val), pkg)!=NULL) { + if(WEXITSTATUS(pclose(pkg))==0) { + if(strtol(val, NULL, 10)==0) + return true; + return false; + } + else { + blacklist(path,ENTER); + return false; + } } - fprintf(write_pipe, "%d\n%c", gauge, 4); - fclose(write_pipe); - dialog_gauge(NULL, "Searching for leaves", maxy/2-1, maxx/2-12, gauge); - fclose(read_pipe); -#endif - lastgauge=gauge; } - sprintf(path,"%s/+REQUIRED_BY",gl.gl_pathv[p]); - if(stat(path,&sb)) { + blacklist(path,ENTER); + pclose(pkg); + return false; + } + else { + sprintf(newpath,"%s/+REQUIRED_BY",path); + if(stat(newpath,&sb)) { switch(errno) { case ENOENT: /* No +REQUIRED_BY, add to list */ - add_item(gl.gl_pathv[p]); + return true; break; default: /* All other errors, add to blacklist */ - blacklist(gl.gl_pathv[p],ENTER); + blacklist(path,ENTER); break; } } else { if(sb.st_size==0) - add_item(gl.gl_pathv[p]); + return true; } + return false; } +} + +/* Goes through the glob contents, looking for zero-length +REQUIRED-BY */ +int read_pkglist(int loops) +{ + if(uses_pkg) { + FILE *pkg; + char line[1024]; + char *p; + + do_init_dialog(); + dialog_msgbox(NULL, "Searching for leaves", 5, 23, FALSE); + fflush(stdout); + pkg=popen("/usr/sbin/pkg query -e \"%#r=0 && %k=0\" \"%n-%v\\t%c\"", "r"); + if(!pkg) { + fputs("Error executing pkg.\n", stderr); + return -1; + } + while(fgets(line, sizeof(line), pkg)!=NULL) { + for(p=strchr(line, 0)-1; p>line && 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); + dlg_clear(); +#endif } - 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(); + 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<pathc;p++) { + gauge=p*100/pathc; + if(gauge != lastgauge) { +#ifdef OLD_DIALOG + dialog_gauge(NULL, "Searching for leaves", maxy/2-1, maxx/2-12, 7, 24, gauge); +#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", gauge, 4); + fclose(write_pipe); + dialog_gauge("", "Searching for leaves", maxy/2-1, maxx/2-12, gauge); + fclose(read_pipe); #endif + lastgauge=gauge; + } + if(is_leaf_package(pathv[p])) { + comment = read_comment(pathv[p]); + add_item(pathv[p], comment); + free(comment); + } + } +#ifdef OLD_DIALOG + dialog_gauge(NULL, "Searching for leaves", maxy/2-1, maxx/2-12, 7, 24, 100); + 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("", "Searching for leaves", maxy/2-1, maxx/2-12, 100); + fclose(read_pipe); + dlg_clear(); +#endif + } if(menulen==0) { if(loops) dialog_msgbox(NULL, "No new leaves found", 5, 23, TRUE); @@ -324,6 +513,7 @@ int read_pkglist(int loops) int remove_ports(void) { + char *cmd; char **args; char *env[1]={NULL}; char **p; @@ -331,8 +521,9 @@ int remove_ports(void) int delete_count=0; pid_t child; int status; + size_t st; - args=(char **)malloc((menulen+2) * sizeof(char *)); + args=(char **)malloc((menulen+4) * sizeof(char *)); if(!args) { do_init_dialog(); dialog_msgbox("ERROR", "Can not allocate memory for package list!", 5, 45, TRUE); @@ -340,7 +531,15 @@ int remove_ports(void) return(-1); } p=args; - *(p++)="-G"; + if(uses_pkg) { + *(p++)="/usr/sbin/pkg"; + *(p++)="delete"; + *(p++)="-y"; + } + else { + *(p++)="/usr/sbin/pkg_delete"; + *(p++)="-G"; + } for(i=0;i<menulen;i++) { if(menu[i].ITEM_CHECKED) { *(p++)=menu[i].ITEM_PROMPT; @@ -360,8 +559,14 @@ int remove_ports(void) endwin(); child=vfork(); if(child==0) { - execve("/usr/sbin/pkg_delete", args, env); + execve(args[0], args, env); fprintf(stderr,"ERROR: %d!\n",errno); +#ifdef OLD_DIALOG + if(helpfile != -1) { + close(helpfile); + unlink(helpfname); + } +#endif _exit(EXIT_FAILURE); } free(args); @@ -375,7 +580,7 @@ int remove_ports(void) /* On an error return, pause */ if(WIFSIGNALED(status) || (WIFEXITED(status) && WEXITSTATUS(status))) { fputs("\n\nPress ENTER to continue... ",stderr); - fgetln(stdin, &i); + fgetln(stdin, &st); } return(0); @@ -391,43 +596,98 @@ int keep_going(void) return(ret); } +int glob_packages(void) +{ + if(uses_pkg) { + FILE *pkg; + char *line; + char *nline; + size_t len; + int ret; + + sl = sl_init(); + fflush(stdout); + pkg = popen("/usr/sbin/pkg query \"%n-%v\"", "r"); + if(!pkg) { + fputs("Unable to get list of packages\n",stderr); + return EX_OSERR; + } + while((line = fgetln(pkg, &len))!=NULL) { + if(len > 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; - - /* 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); - } + int i; + + uses_pkg = check_pkg(); + + i = glob_packages(); + if(i) + return i; - if(gl.gl_pathc==0) { + 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); } |