Date: Sat, 3 Nov 2007 07:19:28 GMT From: Stephen Hurd <shurd@sasktel.net> To: freebsd-gnats-submit@FreeBSD.org Subject: ports/117782: New port: ports-mgmt/pkg_cleanup pkg_rmleaves clone with comment and description viewing Message-ID: <200711030719.lA37JSBf045254@www.freebsd.org> Resent-Message-ID: <200711030720.lA37K1Cq066390@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 117782 >Category: ports >Synopsis: New port: ports-mgmt/pkg_cleanup pkg_rmleaves clone with comment and description viewing >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-ports-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: maintainer-update >Submitter-Id: current-users >Arrival-Date: Sat Nov 03 07:20:01 UTC 2007 >Closed-Date: >Last-Modified: >Originator: Stephen Hurd >Release: 6.2-RELEASE-p6 >Organization: >Environment: FreeBSD server.hurd.local 6.2-RELEASE-p6 FreeBSD 6.2-RELEASE-p6 #3: Tue Jul 24 22:03:03 PDT 2007 root@server.hurd.local:/usr/src/sys/i386/compile/SERVER i386 >Description: This is a simple C clone of ports-mgmt/pkg_rmleaves which shows the package comment and description. >How-To-Repeat: >Fix: Patch attached with submission follows: # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # /usr/ports/ports-mgmt/pkg_cleanup # /usr/ports/ports-mgmt/pkg_cleanup/Makefile # /usr/ports/ports-mgmt/pkg_cleanup/files # /usr/ports/ports-mgmt/pkg_cleanup/files/Makefile # /usr/ports/ports-mgmt/pkg_cleanup/files/pkg_cleanup.c # /usr/ports/ports-mgmt/pkg_cleanup/files/pkg_cleanup.1 # /usr/ports/ports-mgmt/pkg_cleanup/pkg-descr # echo c - /usr/ports/ports-mgmt/pkg_cleanup mkdir -p /usr/ports/ports-mgmt/pkg_cleanup > /dev/null 2>&1 echo x - /usr/ports/ports-mgmt/pkg_cleanup/Makefile sed 's/^X//' >/usr/ports/ports-mgmt/pkg_cleanup/Makefile << 'END-of-/usr/ports/ports-mgmt/pkg_cleanup/Makefile' X# New ports collection makefile for: pkg_cleanup X# Date created: 02 November 2007 X# Whom: Stephen Hurd <shurd@sasktel.net> X# X# $FreeBSD: $ X# X XPORTNAME= pkg_cleanup XPORTVERSION= 1.0 XCATEGORIES= ports-mgmt XDISTFILES= X XMAINTAINER= shurd@sasktel.net XCOMMENT= Interactive program for deinstalling 'leaf' packages X XMAN1= pkg_cleanup.1 X XWRKSRC= ${WRKDIR}/${PORTNAME} X XPLIST_FILES= sbin/pkg_cleanup X Xdo-extract: X ${MKDIR} ${WRKSRC} X ${CP} ${FILESDIR}/* ${WRKSRC} X Xdo-build: X make -C ${WRKSRC} X Xdo-install: X ${INSTALL_PROGRAM} ${WRKSRC}/pkg_cleanup ${PREFIX}/sbin/pkg_cleanup X ${INSTALL_MAN} ${WRKSRC}/pkg_cleanup.1 ${MAN1PREFIX}/man/man1 X X.include <bsd.port.mk> END-of-/usr/ports/ports-mgmt/pkg_cleanup/Makefile echo c - /usr/ports/ports-mgmt/pkg_cleanup/files mkdir -p /usr/ports/ports-mgmt/pkg_cleanup/files > /dev/null 2>&1 echo x - /usr/ports/ports-mgmt/pkg_cleanup/files/Makefile sed 's/^X//' >/usr/ports/ports-mgmt/pkg_cleanup/files/Makefile << 'END-of-/usr/ports/ports-mgmt/pkg_cleanup/files/Makefile' XLDLIBS += -ldialog Xpkg_cleanup: pkg_cleanup.c X END-of-/usr/ports/ports-mgmt/pkg_cleanup/files/Makefile echo x - /usr/ports/ports-mgmt/pkg_cleanup/files/pkg_cleanup.c sed 's/^X//' >/usr/ports/ports-mgmt/pkg_cleanup/files/pkg_cleanup.c << 'END-of-/usr/ports/ports-mgmt/pkg_cleanup/files/pkg_cleanup.c' X#include <sys/param.h> X#include <sys/stat.h> X#include <sys/types.h> X#include <sys/wait.h> X X#include <ctype.h> X#include <curses.h> X#include <dialog.h> X#include <errno.h> X#include <glob.h> X#include <search.h> X#include <stdio.h> X#include <stdlib.h> X#include <string.h> X#include <sysexits.h> X#include <unistd.h> X Xstatic glob_t gl; /* A cached list of all files in /var/db/pkg */ XdialogMenuItem *menu=NULL; Xint menulen=0; X Xvoid free_menu(void) X{ X int i; X X if(menu) { X for(i=0; i<menulen; i++) { X if(menu[i].data) { X free(menu[i].data); X menu[i].data=NULL; X } X if(menu[i].prompt) { X free(menu[i].prompt); X menu[i].prompt=NULL; X } X } X free(menu); X menu=NULL; X menulen=0; X } X} X Xint blacklist(char *path, int operation) X{ X ENTRY item; X X item.data=NULL; X item.key=path; X return(hsearch(item, operation)!=NULL); X} X Xint fire(struct _dmenu_item *item) X{ X if(item->aux) X item->aux=0; X else X item->aux=-1L; X return(DITEM_SUCCESS); X} X Xvoid selected(struct _dmenu_item *item, int is_selected) X{ X char path[MAXPATHLEN+1]; X int maxx,maxy; X X if(is_selected) { X getmaxyx(stdscr, maxy, maxx); X draw_box(stdscr, 3, 2, 3, maxx-4, dialog_attr, border_attr); X wattrset(stdscr, dialog_attr); X mvwaddnstr(stdscr, 4, 4, (char *)item->data, maxx-6); X wrefresh(stdscr); X sprintf(path,"/var/db/pkg/%s/+DESC",item->prompt); X use_helpfile(path); X } X} X Xint checked(struct _dmenu_item *item) X{ X if(item->aux) X return(TRUE); X return(FALSE); X} X X/* Read +COMMENT, add to menu and blacklist */ Xint add_item(char *path) X{ X char *p; X char comment[80]; X FILE *comment_file; X char comment_path[MAXPATHLEN+1]; X dialogMenuItem *newmenu; X X if(blacklist(path,FIND)) X return(0); X blacklist(path,ENTER); X comment[0]=0; X X newmenu=(dialogMenuItem*)realloc(menu, sizeof(dialogMenuItem)*(menulen+1)); X if(newmenu==NULL) X return(-1); X menu=newmenu; X X p=strrchr(path,'/'); X if(p==NULL) /* Not possible */ X return(-1); X X menu[menulen].prompt=strdup(p+1); X menu[menulen].title=""; X menu[menulen].checked=checked; X menu[menulen].fire=fire; X menu[menulen].selected=selected; X menu[menulen].lbra='['; X menu[menulen].mark='X'; X menu[menulen].rbra=']'; X menu[menulen].aux=0; X X /* Read +COMMENT */ X sprintf(comment_path,"%s/+COMMENT",path); X comment_file=fopen(comment_path,"r"); X if(comment_file) { X fgets(comment, sizeof(comment), comment_file); X fclose(comment_file); X /* Remove trailing whitespace */ X for(p=strchr(comment,0)-1; p>=comment; p--) { X if(isspace(*p)) X *p=0; X else X break; X } X } X menu[menulen].data=strdup(comment); X menulen++; X X return(0); X} X Xint display_menu(void) X{ X int ret=0; X int maxx,maxy; X X init_dialog(); X use_shadow=FALSE; X getmaxyx(stdscr, maxy, maxx); X if(dialog_checklist("Welcome to pkg_cleanup.", "These are the leaf packages installed on your system\nChose the packages to deinstall. F1 will display the package description.\n\n\n", maxy, maxx, maxy-11, 0-menulen, menu, NULL)) X ret=-1; X end_dialog(); X return(ret); X} X X/* Goes through the glob contents, looking for zero-length +REQUIRED-BY */ Xint read_pkglist(int loops) X{ X char path[MAXPATHLEN+1]; X int p; X struct stat sb; X int maxx,maxy; X int lastgauge=-1; X int gauge; X X init_dialog(); X getmaxyx(stdscr, maxy, maxx); X for(p=0;p<gl.gl_pathc;p++) { X gauge=p*100/gl.gl_pathc; X if(gauge != lastgauge) { X dialog_gauge(NULL, "Searching for leaves", maxy/2-1, maxx/2-12, 7, 24, gauge); X gauge=lastgauge; X } X sprintf(path,"%s/+REQUIRED_BY",gl.gl_pathv[p]); X if(stat(path,&sb)) { X switch(errno) { X case ENOENT: X /* No +REQUIRED_BY, add to list */ X add_item(gl.gl_pathv[p]); X break; X default: X /* All other errors, add to blacklist */ X blacklist(gl.gl_pathv[p],ENTER); X break; X } X } X else { X if(sb.st_size==0) X add_item(gl.gl_pathv[p]); X } X } X dialog_gauge(NULL, "Searching for leaves", maxy/2-1, maxx/2-12, 7, 24, 100); X dialog_clear_norefresh(); X if(menulen==0) { X if(loops) X dialog_msgbox(NULL, "No new leaves found", 5, 23, TRUE); X else X dialog_msgbox(NULL, "No leaves found", 5, 19, TRUE); X end_dialog(); X return(-1); X } X end_dialog(); X return(0); X} X Xint remove_ports(void) X{ X char **args; X char *env[1]={NULL}; X char **p; X int i; X int delete_count=0; X pid_t child; X int status; X X args=(char **)malloc(menulen+2 * sizeof(char *)); X if(!args) { X init_dialog(); X dialog_msgbox("ERROR", "Can not allocate memory for package list!", 5, 45, TRUE); X end_dialog(); X return(-1); X } X p=args; X *(p++)="-G"; X for(i=0;i<menulen;i++) { X if(menu[i].aux) { X *(p++)=menu[i].prompt; X delete_count++; X } X } X *(p)=NULL; X if(!delete_count) { X init_dialog(); X dialog_msgbox(NULL, "No packages selected", 5, 24, TRUE); X end_dialog(); X free(args); X return(-1); X } X /* Ensure stdio is "right" */ X if(!isendwin()) X endwin(); X child=vfork(); X if(child==0) { X execve("/usr/sbin/pkg_delete", args, env); X fprintf(stderr,"ERROR: %d!\n",errno); X _exit(EXIT_FAILURE); X } X free(args); X if(child==-1) { X init_dialog(); X dialog_msgbox(NULL, "Can not fork()", 5, 18, TRUE); X end_dialog(); X return(-1); X } X waitpid(child, &status, 0); X /* On an error return, pause */ X if(WIFSIGNALED(status) || (WIFEXITED(status) && WEXITSTATUS(status))) { X fputs("\n\nPress ENTER to continue... ",stderr); X fgetln(stdin, &i); X } X X return(0); X} X Xint keep_going(void) X{ X int ret; X X init_dialog(); X ret = !dialog_yesno(NULL,"Do you want to process the new leaves packages?",-1,-1); X end_dialog(); X return(ret); X} X X/* X * The hash table is to keep track of leaves which have already been displayed X * to the user. X */ Xint main(int argc, char **argv) X{ X char **pathv; X struct stat sb; X int loops=0; X X /* glob() package directories */ X if(glob("/var/db/pkg/*", GLOB_ERR, NULL, &gl)) { X fputs("Unable to get list of packages\n",stderr); X switch(errno) { X case GLOB_NOSPACE: X return(EX_UNAVAILABLE); X case GLOB_ABORTED: X return(EX_NOINPUT); X case GLOB_NOMATCH: X return(EX_NOINPUT); X } X return(EXIT_FAILURE); X } X X if(gl.gl_pathc==0) { X fputs("No packages found.\n",stderr); X return(EXIT_FAILURE); X } X X /* Initialize space for blacklist hash table */ X if(hcreate(1000)==0) { X fputs("Cannot create hash table.\n",stderr); X return(EX_UNAVAILABLE); X } X X do { X if(read_pkglist(loops++)) X break; X if(display_menu()) X break; X if(remove_ports()) X break; X free_menu(); X } while(keep_going()); X X fputs("Program Terminated Successfully\n",stderr); X return(0); X} END-of-/usr/ports/ports-mgmt/pkg_cleanup/files/pkg_cleanup.c echo x - /usr/ports/ports-mgmt/pkg_cleanup/files/pkg_cleanup.1 sed 's/^X//' >/usr/ports/ports-mgmt/pkg_cleanup/files/pkg_cleanup.1 << 'END-of-/usr/ports/ports-mgmt/pkg_cleanup/files/pkg_cleanup.1' X.TH PKG_CLEANUP 1 "October 2007" FreeBSD X.SH NAME Xpkg_cleanup \- deinstall 'leaf' packages X.SH SYNOPSIS X.B pkg_cleanup X.SH DESCRIPTION X.B pkg_rmleaves XFinds packages that are not required by any other installed Xpackage and lets you decide (in a dialog interface) for each one Xif you want to delete it. The package comment is shown at the top Xof the screen and F1 will display the full package description. X.P Once the packages marked for removal have been deleted, Xyou'll be asked if you want to do another run (to see packages that have Xbecome 'leaves' now because you've deinstalled the package(s) that Xdepended on them). In every run you will be shown only packages that you Xhaven't marked for keeping, yet. X.P This program was heavily based on the pkg_rmleaves script. The only Xfunctional difference is that this version shows the package comment and XF1 will show the package description. X.SH BUGS Xpkg_cleanup does not display the help line for the first selected Xpackage X.SH AUTHOR XStephen Hurd <shurd@sasktel.net> X.SH SEE ALSO Xpkg_delete(1), pkg_info(1) END-of-/usr/ports/ports-mgmt/pkg_cleanup/files/pkg_cleanup.1 echo x - /usr/ports/ports-mgmt/pkg_cleanup/pkg-descr sed 's/^X//' >/usr/ports/ports-mgmt/pkg_cleanup/pkg-descr << 'END-of-/usr/ports/ports-mgmt/pkg_cleanup/pkg-descr' Xpkg_cleanup finds packages that are not requested by any other installed Xpackage and lets you decide for each one if you want to keep it or delete it. XIt also allows viewing the pacakge comment and description. X XThis program is essentially a clone of pkg_rmleaves except that it shows Xthe comment and description of packages and does not support GUI dialog(1) Ximplementations. END-of-/usr/ports/ports-mgmt/pkg_cleanup/pkg-descr exit >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200711030719.lA37JSBf045254>