diff options
Diffstat (limited to 'usr.sbin/pkg_install/delete')
-rw-r--r-- | usr.sbin/pkg_install/delete/Makefile | 17 | ||||
-rw-r--r-- | usr.sbin/pkg_install/delete/delete.h | 33 | ||||
-rw-r--r-- | usr.sbin/pkg_install/delete/main.c | 123 | ||||
-rw-r--r-- | usr.sbin/pkg_install/delete/perform.c | 216 | ||||
-rw-r--r-- | usr.sbin/pkg_install/delete/pkg_delete.1 | 184 |
5 files changed, 573 insertions, 0 deletions
diff --git a/usr.sbin/pkg_install/delete/Makefile b/usr.sbin/pkg_install/delete/Makefile new file mode 100644 index 0000000..20a5717 --- /dev/null +++ b/usr.sbin/pkg_install/delete/Makefile @@ -0,0 +1,17 @@ +PROG= pkg_delete +CFLAGS+= ${DEBUG} -I${.CURDIR}/../lib + +.if exists(${.OBJDIR}/../lib) +LDADD+= -L${.OBJDIR}/../lib -linstall +DPADD+= ${.OBJDIR}/../lib/libinstall.a +.else +LDADD+= -L${.CURDIR}/../lib -linstall +DPADD+= ${.CURDIR}/../lib/libinstall.a +.endif + +LDADD+= -lftpio -lmd +DPADD+= ${LIBFTPIO} ${LIBMD} + +SRCS= main.c perform.c + +.include <bsd.prog.mk> diff --git a/usr.sbin/pkg_install/delete/delete.h b/usr.sbin/pkg_install/delete/delete.h new file mode 100644 index 0000000..c26345c --- /dev/null +++ b/usr.sbin/pkg_install/delete/delete.h @@ -0,0 +1,33 @@ +/* $Id$ */ + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Include and define various things wanted by the delete command. + * + */ + +#ifndef _INST_DELETE_H_INCLUDE +#define _INST_DELETE_H_INCLUDE + +extern char *Prefix; +extern Boolean NoDeInstall; +extern Boolean CleanDirs; +extern Boolean Force; +extern char *Directory; +extern char *PkgName; + +#endif /* _INST_DELETE_H_INCLUDE */ diff --git a/usr.sbin/pkg_install/delete/main.c b/usr.sbin/pkg_install/delete/main.c new file mode 100644 index 0000000..f9e9717 --- /dev/null +++ b/usr.sbin/pkg_install/delete/main.c @@ -0,0 +1,123 @@ +#ifndef lint +static char *rcsid = "$Id: main.c,v 1.8 1997/02/22 16:09:36 peter Exp $"; +#endif + +/* + * + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * This is the delete module. + * + */ + +#include "lib.h" +#include "delete.h" +#include <err.h> + +static char Options[] = "hvDdnfp:"; + +char *Prefix = NULL; +Boolean NoDeInstall = FALSE; +Boolean CleanDirs = FALSE; + +int +main(int argc, char **argv) +{ + int ch, error; + char **pkgs, **start; + char *prog_name = argv[0]; + + pkgs = start = argv; + while ((ch = getopt(argc, argv, Options)) != -1) + switch(ch) { + case 'v': + Verbose = TRUE; + break; + + case 'f': + Force = TRUE; + break; + + case 'p': + Prefix = optarg; + break; + + case 'D': + NoDeInstall = TRUE; + break; + + case 'd': + CleanDirs = TRUE; + break; + + case 'n': + Fake = TRUE; + Verbose = TRUE; + break; + + case 'h': + case '?': + default: + usage(prog_name, NULL); + break; + } + + argc -= optind; + argv += optind; + + /* Get all the remaining package names, if any */ + /* Get all the remaining package names, if any */ + while (*argv) + *pkgs++ = *argv++; + + /* If no packages, yelp */ + if (pkgs == start) + usage(prog_name, "Missing package name(s)"); + *pkgs = NULL; + if (!Fake && getuid() != 0) + errx(1, "You must be root to delete packages."); + if ((error = pkg_perform(start)) != NULL) { + if (Verbose) + fprintf(stderr, "%d package deletion(s) failed.\n", error); + return error; + } + else + return 0; +} + +void +usage(const char *name, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + if (fmt) { + fprintf(stderr, "%s: ", name); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n\n"); + } + va_end(args); + fprintf(stderr, "Usage: %s [args] pkg [ .. pkg ]\n", name); + fprintf(stderr, "Where args are one or more of:\n\n"); + fprintf(stderr, "-v verbose\n"); + fprintf(stderr, "-p arg override prefix with arg\n"); + fprintf(stderr, "-d delete empty directories when deinstalling\n"); + fprintf(stderr, "-f force delete even if dependencies exist\n"); + fprintf(stderr, " or deinstall/requirement checks fail\n"); + fprintf(stderr, "-D don't execute pkg de-install script, if any\n"); + fprintf(stderr, "-n don't actually de-install, just show steps\n"); + exit(1); +} diff --git a/usr.sbin/pkg_install/delete/perform.c b/usr.sbin/pkg_install/delete/perform.c new file mode 100644 index 0000000..4187a8c --- /dev/null +++ b/usr.sbin/pkg_install/delete/perform.c @@ -0,0 +1,216 @@ +#ifndef lint +static const char *rcsid = "$Id: perform.c,v 1.12 1997/02/22 16:09:37 peter Exp $"; +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * This is the main body of the delete module. + * + */ + +#include "lib.h" +#include "delete.h" + +static int pkg_do(char *); +static void sanity_check(char *); +static void undepend(PackingList, char *); +static char LogDir[FILENAME_MAX]; + + +int +pkg_perform(char **pkgs) +{ + int i, err_cnt = 0; + + for (i = 0; pkgs[i]; i++) + err_cnt += pkg_do(pkgs[i]); + return err_cnt; +} + +static Package Plist; + +/* This is seriously ugly code following. Written very fast! */ +static int +pkg_do(char *pkg) +{ + FILE *cfile; + char home[FILENAME_MAX]; + PackingList p; + char *tmp; + + /* Reset some state */ + if (Plist.head) + free_plist(&Plist); + + sprintf(LogDir, "%s/%s", (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR, + pkg); + if (!fexists(LogDir)) { + whinge("No such package '%s' installed.", pkg); + return 1; + } + if (!getcwd(home, FILENAME_MAX)) + barf("Unable to get current working directory!"); + if (chdir(LogDir) == FAIL) { + whinge("Unable to change directory to %s! Deinstall failed.", LogDir); + return 1; + } + if (!isemptyfile(REQUIRED_BY_FNAME)) { + char buf[512]; + whinge("Package `%s' is required by these other packages", pkg); + whinge("and may not be deinstalled%s:", Force ? " (but I'll delete it anyway)" : "" ); + cfile = fopen(REQUIRED_BY_FNAME, "r"); + if (cfile) { + while (fgets(buf, sizeof(buf), cfile)) + fprintf(stderr, "%s", buf); + fclose(cfile); + } else + whinge("cannot open requirements file `%s'", REQUIRED_BY_FNAME); + if (!Force) + return 1; + } + sanity_check(LogDir); + cfile = fopen(CONTENTS_FNAME, "r"); + if (!cfile) { + whinge("Unable to open '%s' file.", CONTENTS_FNAME); + return 1; + } + /* If we have a prefix, add it now */ + if (Prefix) + add_plist(&Plist, PLIST_CWD, Prefix); + read_plist(&Plist, cfile); + fclose(cfile); + p = find_plist(&Plist, PLIST_CWD); + if (!p) { + whinge("Package '%s' doesn't have a prefix.", pkg); + return 1; + } + setenv(PKG_PREFIX_VNAME, p->name, 1); + if (fexists(REQUIRE_FNAME)) { + if (Verbose) + printf("Executing 'require' script.\n"); + vsystem("chmod +x %s", REQUIRE_FNAME); /* be sure */ + if (vsystem("./%s %s DEINSTALL", REQUIRE_FNAME, pkg)) { + whinge("Package %s fails requirements %s", pkg, + Force ? "." : "- not deleted."); + if (!Force) + return 1; + } + } + if (!NoDeInstall && fexists(DEINSTALL_FNAME)) { + if (Fake) + printf("Would execute de-install script at this point.\n"); + else { + vsystem("chmod +x %s", DEINSTALL_FNAME); /* make sure */ + if (vsystem("./%s %s DEINSTALL", DEINSTALL_FNAME, pkg)) { + whinge("De-Install script returned error status."); + if (!Force) + return 1; + } + } + } + if (chdir(home) == FAIL) + barf("Toto! This doesn't look like Kansas anymore!"); + if (!Fake) { + /* Some packages aren't packed right, so we need to just ignore delete_package()'s status. Ugh! :-( */ + if (delete_package(FALSE, CleanDirs, &Plist) == FAIL) + whinge("Couldn't entirely delete package (perhaps the packing list is\n" + "incorrectly specified?)\n"); + if (vsystem("%s -r %s", REMOVE_CMD, LogDir)) { + whinge("Couldn't remove log entry in %s, de-install failed.", LogDir); + if (!Force) + return 1; + } + } + for (p = Plist.head; p ; p = p->next) { + if (p->type != PLIST_PKGDEP) + continue; + if (Verbose) + printf("Attempting to remove dependency on package `%s'\n", p->name); + if (!Fake) + undepend(p, pkg); + } + return 0; +} + +static void +sanity_check(char *pkg) +{ + if (!fexists(CONTENTS_FNAME)) + barf("Installed package %s has no %s file!", pkg, CONTENTS_FNAME); +} + +void +cleanup(int sig) +{ + /* Nothing to do */ +} + +static void +undepend(PackingList p, char *pkgname) +{ + char fname[FILENAME_MAX], ftmp[FILENAME_MAX]; + char fbuf[FILENAME_MAX]; + FILE *fp, *fpwr; + char *tmp; + int s; + + sprintf(fname, "%s/%s/%s", + (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR, + p->name, REQUIRED_BY_FNAME); + fp = fopen(fname, "r"); + if (fp == NULL) { + whinge("Couldn't open dependency file `%s'", fname); + return; + } + sprintf(ftmp, "%s.XXXXXX", fname); + s = mkstemp(ftmp); + if (s == -1) { + fclose(fp); + whinge("Couldn't open temp file `%s'", ftmp); + return; + } + fpwr = fdopen(s, "w"); + if (fpwr == NULL) { + close(s); + fclose(fp); + whinge("Couldn't fdopen temp file `%s'", ftmp); + remove(ftmp); + return; + } + while (fgets(fbuf, sizeof(fbuf), fp) != NULL) { + if (fbuf[strlen(fbuf)-1] == '\n') + fbuf[strlen(fbuf)-1] = '\0'; + if (strcmp(fbuf, pkgname)) /* no match */ + fputs(fbuf, fpwr), putc('\n', fpwr); + } + (void) fclose(fp); + if (fchmod(s, 0644) == FAIL) { + whinge("Error changing permission of temp file `%s'", ftmp); + fclose(fpwr); + remove(ftmp); + return; + } + if (fclose(fpwr) == EOF) { + whinge("Error closing temp file `%s'", ftmp); + remove(ftmp); + return; + } + if (rename(ftmp, fname) == -1) + whinge("Error renaming `%s' to `%s'", ftmp, fname); + remove(ftmp); /* just in case */ + return; +} diff --git a/usr.sbin/pkg_install/delete/pkg_delete.1 b/usr.sbin/pkg_install/delete/pkg_delete.1 new file mode 100644 index 0000000..ad9b0a5 --- /dev/null +++ b/usr.sbin/pkg_install/delete/pkg_delete.1 @@ -0,0 +1,184 @@ +.\" +.\" FreeBSD install - a package for the installation and maintainance +.\" of non-core utilities. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" Jordan K. Hubbard +.\" +.\" +.\" @(#)pkg_delete.1 +.\" +.Dd November 25, 1994 +.Dt pkg_delete 1 +.Os FreeBSD 2.0 +.Sh NAME +.Nm pkg_delete +.Nd a utility for deleting previously installed software package distributions. +.Sh SYNOPSIS +.Nm +.Op Fl vDdnf +.Op Fl p Ar prefix +.Ar pkg-name ... +.Sh DESCRIPTION +The +.Nm +command is used to delete packages that have been previously installed +with the +.Xr pkg_add 1 +command. + +.Sh WARNING +.Bf -emphasis +Since the +.Nm +command may execute scripts or programs provided by a package file, +your system may be susceptible to ``trojan horses'' or other subtle +attacks from miscreants who create dangerous package files. +.Pp +You are advised to verify the competence and identity of those who +provide installable package files. For extra protection, examine all +the package control files in the package record directory ( +.Pa /var/db/pkg/<pkg-name>/ ). +Pay particular +attention to any +INSTALL, +DEINSTALL, +REQUIRE or +MTREE_DIRS files, +and inspect the +CONTENTS file for +.Cm @cwd , +.Cm @mode +(check for setuid), +.Cm @dirrm , +.Cm @exec , +and +.Cm @unexec +directives, and/or use the +.Xr pkg_info 1 +command to examine the installed package control files. +.Ef + +.Sh OPTIONS +The following command line options are supported. +.Bl -tag -width indent +.It Ar pkg-name ... +The named packages are deinstalled. +.It Fl v +Turns on verbose output. +.Em "Optional." +.It Fl D +If a deinstallation script exists for a given package, do not execute it. +.Em "Optional." +.It Fl n +Don't actually deinstall a package, just report the steps that +would be taken if it were. +.Em "Optional." +.It Fl p Ar prefix +Sets +.Ar prefix +as the directory in which to delete files from any installed packages +which do not explicitly set theirs. For most packages, the prefix will +be set automatically to the installed location by +.Xr pkg_add 1 . +.Em "Optional." +.It Fl d +Remove empty directories created by file cleanup. By default, only +files/directories explicitly listed in a package's contents (either as +normal files/directories or with the +.Cm @dirrm +directive) will be removed at deinstallation time. This option tells +.Nm +to also remove any directories that were emptied as a result of removing +the package. +.Em "Optional." +.It Fl f +Force removal of the package, even if a dependency is recorded or the +deinstall or require script fails. +.Em "Optional." +.El + +.Pp +.Sh TECHNICAL DETAILS +.Nm +does pretty much what it says. It examines installed package records in +.Pa /var/db/pkg/<pkg-name> , +deletes the package contents, and finally removes the package records. +.Pp +If a package is required by other installed packages, +.Nm +will list those dependent packages and refuse to delete the package +(unless the +.Fl f +option is given). +.Pp +If the package contains a +.Ar require +file (see +.Xr pkg_create 1 ), +then this is executed first as +.Bd -filled -offset indent -compact +.Cm require +.Ar <pkg-name> +.Ar DEINSTALL +.Ed +(where +.Ar pkg-name +is the name of the package in question and +.Ar DEINSTALL +is a keyword denoting that this is a deinstallation) +to see whether or not deinstallation should continue. A non-zero exit +status means no, unless the +.Fl f +option is specified. +.Pp +If a +.Cm deinstall +script exists for the package, it is executed before any files are removed. +It is this script's responsibility to clean up any additional messy details +around the package's installation, since all +.Nm +knows how to do is delete the files created in the original distribution. +The +.Nm deinstall +script is called as: +.Bd -filled -offset indent -compact +.Cm deinstall +.Ar <pkg-name> +.Ar DEINSTALL +.Ed +Passing the keyword +.Ar DEINSTALL +lets you potentially write only one program/script that handles all +aspects of installation and deletion. +.Pp +All scripts are called with the environment variable +.Ev PKG_PREFIX +set to the installation prefix (see the +.Fl p +option above). This allows a package author to write a script +that reliably performs some action on the directory where the package +is installed, even if the user might have changed it by specifying the +.Fl p +option when running +.Nm +or +.Cm pkg_add . +.Sh SEE ALSO +.Xr pkg_add 1 , +.Xr pkg_create 1 , +.Xr pkg_info 1 , +.Xr mktemp 3 , +.Xr mtree 8 . +.Sh AUTHORS +.Bl -tag -width indent -compact +.It "Jordan Hubbard" +most of the work +.It "John Kohl" +refined it for NetBSD +.El +.Sh BUGS +Sure to be some. |