Skip site navigation (1)Skip section navigation (2)
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>