aboutsummaryrefslogtreecommitdiff
path: root/ports-mgmt/pkg_cleanup
diff options
context:
space:
mode:
authorPav Lucistnik <pav@FreeBSD.org>2008-01-04 13:28:51 +0000
committerPav Lucistnik <pav@FreeBSD.org>2008-01-04 13:28:51 +0000
commit13e69f8e3732d419d02d3777b09e88185f3fb502 (patch)
treeab933b91d394bd051df78fef08b2c67ecf11e21b /ports-mgmt/pkg_cleanup
parente0f2dda31eed07e084ba6ca919a3af8a41a0e989 (diff)
downloadports-13e69f8e3732d419d02d3777b09e88185f3fb502.tar.gz
ports-13e69f8e3732d419d02d3777b09e88185f3fb502.zip
Notes
Diffstat (limited to 'ports-mgmt/pkg_cleanup')
-rw-r--r--ports-mgmt/pkg_cleanup/Makefile33
-rw-r--r--ports-mgmt/pkg_cleanup/files/Makefile5
-rw-r--r--ports-mgmt/pkg_cleanup/files/pkg_cleanup.126
-rw-r--r--ports-mgmt/pkg_cleanup/files/pkg_cleanup.c317
-rw-r--r--ports-mgmt/pkg_cleanup/pkg-descr7
5 files changed, 388 insertions, 0 deletions
diff --git a/ports-mgmt/pkg_cleanup/Makefile b/ports-mgmt/pkg_cleanup/Makefile
new file mode 100644
index 000000000000..25d22ec83b03
--- /dev/null
+++ b/ports-mgmt/pkg_cleanup/Makefile
@@ -0,0 +1,33 @@
+# New ports collection makefile for: pkg_cleanup
+# Date created: 02 November 2007
+# Whom: Stephen Hurd <shurd@sasktel.net>
+#
+# $FreeBSD$
+#
+
+PORTNAME= pkg_cleanup
+PORTVERSION= 1.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
+
+do-extract:
+ ${MKDIR} ${WRKSRC}
+ ${CP} -R ${FILESDIR}/* ${WRKSRC}
+
+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
+
+.include <bsd.port.mk>
diff --git a/ports-mgmt/pkg_cleanup/files/Makefile b/ports-mgmt/pkg_cleanup/files/Makefile
new file mode 100644
index 000000000000..e5271323fc1d
--- /dev/null
+++ b/ports-mgmt/pkg_cleanup/files/Makefile
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+LDLIBS += -ldialog
+pkg_cleanup: pkg_cleanup.c
+
diff --git a/ports-mgmt/pkg_cleanup/files/pkg_cleanup.1 b/ports-mgmt/pkg_cleanup/files/pkg_cleanup.1
new file mode 100644
index 000000000000..56f55a8b2f7a
--- /dev/null
+++ b/ports-mgmt/pkg_cleanup/files/pkg_cleanup.1
@@ -0,0 +1,26 @@
+.TH PKG_CLEANUP 1 "October 2007" FreeBSD
+.SH NAME
+pkg_cleanup \- deinstall 'leaf' packages
+.SH SYNOPSIS
+.B pkg_cleanup
+.SH DESCRIPTION
+.B pkg_rmleaves
+Finds packages that are not required by any other installed
+package and lets you decide (in a dialog interface) for each one
+if you want to delete it. The package comment is shown at the top
+of the screen and F1 will display the full package description.
+.P Once the packages marked for removal have been deleted,
+you'll be asked if you want to do another run (to see packages that have
+become 'leaves' now because you've deinstalled the package(s) that
+depended on them). In every run you will be shown only packages that you
+haven't marked for keeping, yet.
+.P This program was heavily based on the pkg_rmleaves script. The only
+functional difference is that this version shows the package comment and
+F1 will show the package description.
+.SH BUGS
+pkg_cleanup does not display the help line for the first selected
+package
+.SH AUTHOR
+Stephen Hurd <shurd@sasktel.net>
+.SH SEE ALSO
+pkg_delete(1), pkg_info(1)
diff --git a/ports-mgmt/pkg_cleanup/files/pkg_cleanup.c b/ports-mgmt/pkg_cleanup/files/pkg_cleanup.c
new file mode 100644
index 000000000000..1027557759d3
--- /dev/null
+++ b/ports-mgmt/pkg_cleanup/files/pkg_cleanup.c
@@ -0,0 +1,317 @@
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <ctype.h>
+#include <curses.h>
+#include <dialog.h>
+#include <errno.h>
+#include <glob.h>
+#include <search.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+static glob_t gl; /* A cached list of all files in /var/db/pkg */
+dialogMenuItem *menu=NULL;
+int menulen=0;
+
+void free_menu(void)
+{
+ int i;
+
+ if(menu) {
+ for(i=0; i<menulen; i++) {
+ if(menu[i].data) {
+ free(menu[i].data);
+ menu[i].data=NULL;
+ }
+ if(menu[i].prompt) {
+ free(menu[i].prompt);
+ menu[i].prompt=NULL;
+ }
+ }
+ free(menu);
+ menu=NULL;
+ menulen=0;
+ }
+}
+
+int blacklist(char *path, int operation)
+{
+ ENTRY item;
+
+ item.data=NULL;
+ item.key=path;
+ return(hsearch(item, operation)!=NULL);
+}
+
+int fire(struct _dmenu_item *item)
+{
+ if(item->aux)
+ item->aux=0;
+ else
+ item->aux=-1L;
+ return(DITEM_SUCCESS);
+}
+
+void selected(struct _dmenu_item *item, int is_selected)
+{
+ char path[MAXPATHLEN+1];
+ int maxx,maxy;
+
+ if(is_selected) {
+ getmaxyx(stdscr, maxy, maxx);
+ draw_box(stdscr, 3, 2, 3, maxx-4, dialog_attr, border_attr);
+ 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);
+ }
+}
+
+int checked(struct _dmenu_item *item)
+{
+ if(item->aux)
+ return(TRUE);
+ return(FALSE);
+}
+
+/* Read +COMMENT, add to menu and blacklist */
+int add_item(char *path)
+{
+ char *p;
+ char comment[80];
+ FILE *comment_file;
+ char comment_path[MAXPATHLEN+1];
+ dialogMenuItem *newmenu;
+
+ if(blacklist(path,FIND))
+ return(0);
+ blacklist(path,ENTER);
+ comment[0]=0;
+
+ newmenu=(dialogMenuItem*)realloc(menu, sizeof(dialogMenuItem)*(menulen+1));
+ if(newmenu==NULL)
+ return(-1);
+ menu=newmenu;
+
+ p=strrchr(path,'/');
+ if(p==NULL) /* Not possible */
+ return(-1);
+
+ menu[menulen].prompt=strdup(p+1);
+ menu[menulen].title="";
+ menu[menulen].checked=checked;
+ menu[menulen].fire=fire;
+ menu[menulen].selected=selected;
+ menu[menulen].lbra='[';
+ menu[menulen].mark='X';
+ menu[menulen].rbra=']';
+ menu[menulen].aux=0;
+
+ /* Read +COMMENT */
+ sprintf(comment_path,"%s/+COMMENT",path);
+ comment_file=fopen(comment_path,"r");
+ if(comment_file) {
+ fgets(comment, sizeof(comment), comment_file);
+ fclose(comment_file);
+ /* Remove trailing whitespace */
+ for(p=strchr(comment,0)-1; p>=comment; p--) {
+ if(isspace(*p))
+ *p=0;
+ else
+ break;
+ }
+ }
+ menu[menulen].data=strdup(comment);
+ menulen++;
+
+ return(0);
+}
+
+int display_menu(void)
+{
+ int ret=0;
+ int maxx,maxy;
+
+ init_dialog();
+ use_shadow=FALSE;
+ getmaxyx(stdscr, maxy, maxx);
+ 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))
+ ret=-1;
+ end_dialog();
+ return(ret);
+}
+
+/* Goes through the glob contents, looking for zero-length +REQUIRED-BY */
+int read_pkglist(int loops)
+{
+ char path[MAXPATHLEN+1];
+ int p;
+ struct stat sb;
+ int maxx,maxy;
+ int lastgauge=-1;
+ int gauge;
+
+ init_dialog();
+ getmaxyx(stdscr, maxy, maxx);
+ for(p=0;p<gl.gl_pathc;p++) {
+ gauge=p*100/gl.gl_pathc;
+ if(gauge != lastgauge) {
+ dialog_gauge(NULL, "Searching for leaves", maxy/2-1, maxx/2-12, 7, 24, gauge);
+ gauge=lastgauge;
+ }
+ sprintf(path,"%s/+REQUIRED_BY",gl.gl_pathv[p]);
+ if(stat(path,&sb)) {
+ switch(errno) {
+ case ENOENT:
+ /* No +REQUIRED_BY, add to list */
+ add_item(gl.gl_pathv[p]);
+ break;
+ default:
+ /* All other errors, add to blacklist */
+ blacklist(gl.gl_pathv[p],ENTER);
+ break;
+ }
+ }
+ else {
+ if(sb.st_size==0)
+ add_item(gl.gl_pathv[p]);
+ }
+ }
+ dialog_gauge(NULL, "Searching for leaves", maxy/2-1, maxx/2-12, 7, 24, 100);
+ dialog_clear_norefresh();
+ if(menulen==0) {
+ if(loops)
+ dialog_msgbox(NULL, "No new leaves found", 5, 23, TRUE);
+ else
+ dialog_msgbox(NULL, "No leaves found", 5, 19, TRUE);
+ end_dialog();
+ return(-1);
+ }
+ end_dialog();
+ return(0);
+}
+
+int remove_ports(void)
+{
+ char **args;
+ char *env[1]={NULL};
+ char **p;
+ int i;
+ int delete_count=0;
+ pid_t child;
+ int status;
+
+ args=(char **)malloc(menulen+2 * sizeof(char *));
+ if(!args) {
+ init_dialog();
+ dialog_msgbox("ERROR", "Can not allocate memory for package list!", 5, 45, TRUE);
+ end_dialog();
+ return(-1);
+ }
+ p=args;
+ *(p++)="-G";
+ for(i=0;i<menulen;i++) {
+ if(menu[i].aux) {
+ *(p++)=menu[i].prompt;
+ delete_count++;
+ }
+ }
+ *(p)=NULL;
+ if(!delete_count) {
+ init_dialog();
+ dialog_msgbox(NULL, "No packages selected", 5, 24, TRUE);
+ end_dialog();
+ free(args);
+ return(-1);
+ }
+ /* Ensure stdio is "right" */
+ if(!isendwin())
+ endwin();
+ child=vfork();
+ if(child==0) {
+ execve("/usr/sbin/pkg_delete", args, env);
+ fprintf(stderr,"ERROR: %d!\n",errno);
+ _exit(EXIT_FAILURE);
+ }
+ free(args);
+ if(child==-1) {
+ init_dialog();
+ dialog_msgbox(NULL, "Can not fork()", 5, 18, TRUE);
+ end_dialog();
+ return(-1);
+ }
+ waitpid(child, &status, 0);
+ /* On an error return, pause */
+ if(WIFSIGNALED(status) || (WIFEXITED(status) && WEXITSTATUS(status))) {
+ fputs("\n\nPress ENTER to continue... ",stderr);
+ fgetln(stdin, &i);
+ }
+
+ return(0);
+}
+
+int keep_going(void)
+{
+ int ret;
+
+ init_dialog();
+ ret = !dialog_yesno(NULL,"Do you want to process the new leaves packages?",-1,-1);
+ end_dialog();
+ return(ret);
+}
+
+/*
+ * 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);
+ }
+
+ if(gl.gl_pathc==0) {
+ fputs("No packages found.\n",stderr);
+ return(EXIT_FAILURE);
+ }
+
+ /* Initialize space for blacklist hash table */
+ if(hcreate(1000)==0) {
+ fputs("Cannot create hash table.\n",stderr);
+ return(EX_UNAVAILABLE);
+ }
+
+ do {
+ if(read_pkglist(loops++))
+ break;
+ if(display_menu())
+ break;
+ if(remove_ports())
+ break;
+ free_menu();
+ } while(keep_going());
+
+ fputs("Program Terminated Successfully\n",stderr);
+ return(0);
+}
diff --git a/ports-mgmt/pkg_cleanup/pkg-descr b/ports-mgmt/pkg_cleanup/pkg-descr
new file mode 100644
index 000000000000..262cf9984d74
--- /dev/null
+++ b/ports-mgmt/pkg_cleanup/pkg-descr
@@ -0,0 +1,7 @@
+pkg_cleanup finds packages that are not requested by any other installed
+package and lets you decide for each one if you want to keep it or delete it.
+It also allows viewing the pacakge comment and description.
+
+This program is essentially a clone of pkg_rmleaves except that it shows
+the comment and description of packages and does not support GUI dialog(1)
+implementations.